import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'
import cssStyle from './index.module.css'

class TooltipComponent extends React.Component{
    timer = null
    ref = React.createRef()
    show = () => {
        if(!this.props.open){
            return
        }
        let placementList = ['bottom-left', 'bottom-center', 'bottom-right', 'top-left', 'top-center', 'top-right', 'left-top', 'left-center', 'left-bottom', 'right-top', 'right-center', 'right-bottom']
        if(placementList.indexOf(this.props.placement) === -1){
            console.error('Invalid props: placement')
        } else {
            let mainRef = this.ref.current
            let containerRef = mainRef.getElementsByTagName('span')[0]
            let triangleRef = mainRef.getElementsByTagName('span')[1]
            mainRef.style.display = 'block'
            containerRef.innerHTML = this.props.title
            window.requestAnimationFrame(() => {
                setTimeout(() => {
                    mainRef.style.opacity = 1
                    let { width, height, top, left, bottom } = this.props.position
                    let placement = this.props.placement.split('-')
                    if(placement[0] === 'bottom'){
                        mainRef.style.top = bottom + 5 + 'px'
                        triangleRef.style.left = '50%'
                        triangleRef.style.right = 'unset'
                        triangleRef.style.top = '-5px'
                        triangleRef.style.bottom = 'unset'
                        triangleRef.style.transform = 'translateX(-50%) rotate(0)'
                    }
                    if(placement[0] === 'top'){
                        mainRef.style.top = top - mainRef.offsetHeight - 5 + 'px'
                        triangleRef.style.left = '50%'
                        triangleRef.style.right = 'unset'
                        triangleRef.style.top = 'unset'
                        triangleRef.style.bottom = '-5px'
                        triangleRef.style.transform = 'translateX(-50%) rotate(180deg)'
                    }
                    if(placement[0] === 'left'){
                        mainRef.style.left = left - mainRef.offsetWidth - 5 + 'px'
                        triangleRef.style.left = 'unset'
                        triangleRef.style.right = '-7px'
                        triangleRef.style.top = '50%'
                        triangleRef.style.bottom = 'unset'
                        triangleRef.style.transform = 'translateY(-50%) rotate(90deg)'
                    }
                    if(placement[0] === 'right'){
                        mainRef.style.left = left + width + 5 + 'px'
                        triangleRef.style.left = '-7px'
                        triangleRef.style.right = 'unset'
                        triangleRef.style.top = '50%'
                        triangleRef.style.bottom = 'unset'
                        triangleRef.style.transform = 'translateY(-50%) rotate(-90deg)'
                    }
                    if(placement[0] === 'bottom' || placement[0] === 'top'){
                        if (placement[1] === 'left') {
                            mainRef.style.left = left + 'px'
                        }
                        if (placement[1] === 'center') {
                            mainRef.style.left = left + width/2 - mainRef.offsetWidth/2 + 'px'
                        }
                        if (placement[1] === 'right') {
                            mainRef.style.left = left + width - mainRef.offsetWidth + 'px'
                        }
                    }
                    if(placement[0] === 'left' || placement[0] === 'right'){
                        if (placement[1] === 'top') {
                            mainRef.style.top = top + 'px'
                        }
                        if (placement[1] === 'center') {
                            mainRef.style.top = top + height/2 - mainRef.offsetHeight/2 + 'px'
                        }
                        if (placement[1] === 'bottom') {
                            mainRef.style.top = top + height - mainRef.offsetHeight + 'px'
                        }
                    }
                })
            })
        }
    }
    hide = () => {
        this.ref.current.style.opacity = 0
        this.timer = setTimeout(() => {
            if(this.ref.current){
                this.ref.current.style.display = 'none'
            }
        }, 300)
    }
    componentDidUpdate(){
        if(this.timer){
            clearTimeout(this.timer)
            this.timer = null
        }
        if(this.props.open){
            this.show()
        }else{
            this.hide()
        }
    }
    componentDidMount(){
        setTimeout(() => {
            this.show()
        })
    }
    render(){
        return(
            <div ref={ this.ref } className={ cssStyle.tooltip }>
                <span></span>
                <span className={ cssStyle.triangle + ' ' + cssStyle.triangleUp }></span>
            </div>
        )
    }
}

TooltipComponent.propTypes = {
    placement: PropTypes.string,
    title: PropTypes.string,
    position: PropTypes.object,
    open: PropTypes.bool
}
TooltipComponent.defaultProps = {
    placement: 'bottom-center'
}

let container = null
export default class Tooltip extends React.Component{
    toggle = (open, position) => {
        if(open){
            if(!container){
                container = document.createElement('div')
                document.body.appendChild(container)
            }
        }
        if(container){
            ReactDOM.render(
                <TooltipComponent {...this.props} position={ position } open={ open } />,
                container
            )
        }
    }
    mouseEnter = e => {
        if(this.props.children.props.onMouseEnter){
            this.props.children.props.onMouseEnter()
        }
        if (!this.props.hide) {
            let position = e.currentTarget.getBoundingClientRect()
            this.toggle(true, position)
        }
    }
    mouseLeave = e => {
        if(this.props.children.props.onMouseLeave){
            this.props.children.props.onMouseLeave()
        }
        if (!this.props.hide) {
            let position = e.currentTarget.getBoundingClientRect()
            this.toggle(false, position)
        }
    }
    componentDidUpdate() {
        if (this.props.hide) {
            this.toggle(false, null)
        }
    }
    componentWillUnmount() {
        this.toggle(false, null)
    }
    render(){
        return React.Children.map(this.props.children, item => {
            if(item){
                return React.cloneElement(item, {
                    onMouseEnter: this.mouseEnter,
                    onMouseLeave: this.mouseLeave
                })
            }
        })
    }
}

Tooltip.propTypes = {
    children: PropTypes.object,
    hide: PropTypes.bool
}